package com.qingcheng.task;


import com.alibaba.fastjson.JSON;
import com.qingcheng.dao.SeckillGoodsMapper;
import com.qingcheng.pojo.seckill.SeckillGoods;
import com.qingcheng.pojo.seckill.SeckillOrder;
import com.qingcheng.util.IdWorker;
import com.qingcheng.pojo.seckill.SeckillStatus;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 多线程异步操作类
 */
@Component
public class MultiThreadingCreateOrder {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private IdWorker idWorker;

    /**
     * 异步操作方法
     */
    @Async
    public void createOrder() {
        try {
            System.out.println("准备执行.....");
            Thread.sleep(10000);

            SeckillStatus seckillStatus = (SeckillStatus) redisTemplate.boundListOps("SeckillOrderQueue").rightPop();
            //用户抢单数据
            String username = seckillStatus.getUsername();
            String time = seckillStatus.getTime();
            Long id = seckillStatus.getGoodsId();

            //获取队列中的id
            Object sid = redisTemplate.boundListOps("SeckillGoodsCountList_" + id).rightPop();

            //售罄
            if (sid == null) {
                //清理当前用户的排队信息
                clearQueue(seckillStatus);
                return;
            }

            //获取商品数据
            SeckillGoods goods = (SeckillGoods) redisTemplate.boundHashOps("SeckillGoods_" + time).get(id);

            Thread.sleep(10000);//制造超卖问题
            //如果没有库存，则直接抛出异常
            if (goods == null || goods.getStockCount() <= 0) {
                throw new RuntimeException("已售罄!");
            }
            //如果有库存，则创建秒杀商品订单
            SeckillOrder seckillOrder = new SeckillOrder();
            seckillOrder.setId(idWorker.nextId());
            seckillOrder.setSeckillId(id);
            seckillOrder.setMoney(goods.getCostPrice());
            seckillOrder.setUserId(username);
            seckillOrder.setSellerId(goods.getSellerId());
            seckillOrder.setCreateTime(new Date());
            seckillOrder.setStatus("0");
            //将秒杀订单存入到Redis中
            redisTemplate.boundHashOps("SeckillOrder").put(username, seckillOrder);
            //库存减少
            Long surplusCount = redisTemplate.boundHashOps("SeckillGoodsCount").increment(goods.getId(), -1);
            goods.setStockCount(surplusCount.intValue());
            //判断当前商品是否还有库存
            if (surplusCount <= 0) {
                //并且将商品数据同步到MySQL中
                seckillGoodsMapper.updateByPrimaryKeySelective(goods);
                //如果没有库存,则清空Redis缓存中该商品
                redisTemplate.boundHashOps("SeckillGoods_" + time).delete(id);
            } else {
                //如果有库存，则直数据重置到Reids中
                redisTemplate.boundHashOps("SeckillGoods_" + time).put(id, goods);

            }
            //变更抢单状态
            seckillStatus.setOrderId(seckillOrder.getId());
            seckillStatus.setMoney(seckillOrder.getMoney().floatValue());
            seckillStatus.setStatus(2); //抢单成功,待支付
            redisTemplate.boundHashOps("UserQueueStatus").put(username, seckillStatus);

            System.out.println("正在执行.....");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /***
     *  清理用户排队信息
     *  @param seckillStatus
     */
    public void clearQueue(SeckillStatus seckillStatus) {
        //清理排队标示
        redisTemplate.boundHashOps("UserQueueCount").delete(seckillStatus.getUsername());
        //清理抢单标示
        redisTemplate.boundHashOps("UserQueueStatus").delete(seckillStatus.getUsername());
    }


    @Autowired
    private RabbitTemplate rabbitTemplate;

    /***
     * 延时消息发送
     * @param seckillStatus
     */
    public void sendDelayMessage(SeckillStatus seckillStatus) {
        rabbitTemplate.convertAndSend("exchange.delay.order.begin",
                "delay",
                JSON.toJSONString(seckillStatus),
                new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //消息有效期30分钟
                // message.getMessageProperties().setExpiration(String.valueOf(1800000));
                message.getMessageProperties().setExpiration(String.valueOf(10000));
                return message;
            }
        });
    }

}
